1 : <?php
2 : /*--------------------------------------------------------------------------+
3 : This file is part of eStudy.
4 : planspiel/classes/class.phase.inc.php
5 : - Modulgruppe: Planspiel
6 : - Beschreibung: Erstellen eines Phasen-Objektes mit entsprechenden Funktionen.
7 : - Version: 0.6, 10/16/06
8 : - Autor(en): Clemens Weiß <clemens.weiss@mni.fh-giessen.de>
9 : +---------------------------------------------------------------------------+
10 : This program is free software; you can redistribute it and/or
11 : modify it under the terms of the GNU General Public License
12 : as published by the Free Software Foundation; either version 2
13 : of the License, or any later version.
14 : +---------------------------------------------------------------------------+
15 : This program is distributed in the hope that it will be useful,
16 : but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : GNU General Public License for more details.
19 : You should have received a copy of the GNU General Public License
20 : along with this program; if not, write to the Free Software
21 : Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 : +--------------------------------------------------------------------------*/
23 : /**
24 : * Erstellen eines Phasen-Objektes mit entsprechenden Funktionen.
25 : * @package eStudy.Planspiel
26 : * @version 0.6, 16/12/06
27 : * @author Clemens Weiß <clemens.weiss@mni.fh-giessen.de>
28 : */
29 1 : require_once ("class.userrolemanagement.inc.php");
30 1 : require_once ("class.userteammanagement.inc.php");
31 1 : require_once ("class.teamlist.inc.php");
32 1 : require_once ("class.team.inc.php");
33 1 : require_once ("class.planspiel.inc.php");
34 :
35 1 : require_once ("class.dateselection.inc.php");
36 :
37 1 : require_once ("class.document.inc.php");
38 1 : class Phase {
39 : /**
40 : * ID der Phase
41 : * @var int
42 : * @access private
43 : */
44 : var $ID;
45 : /**
46 : * ID des Planspiels, das die Phase enthält
47 : * @var int
48 : * @access private
49 : */
50 : var $planspielID;
51 : /**
52 : * Name der Phase
53 : * @var string
54 : * @access private
55 : */
56 : var $name;
57 : /**
58 : * Beschreibung der Phase
59 : * @var string
60 : * @access private
61 : */
62 : var $description;
63 : /**
64 : * ID des für diese Phase verantwortlichen Benutzers
65 : * @var int
66 : * @access private
67 : */
68 : var $responsibleUserID;
69 : /**
70 : * Position dieser Phase zwischen den anderen des Planspiels
71 : * @var int
72 : * @access private
73 : */
74 : var $order;
75 : /**
76 : * Gibt an, ob diese Phase ein Meilenstein ist
77 : * @var boolean
78 : * @access private
79 : */
80 : var $isMilestone;
81 : /**
82 : * Gibt an, ob diese Phase abgeschlossen ist
83 : * @var boolean
84 : * @access private
85 : */
86 : var $isFinished;
87 : /**
88 : * Gibt an, wann diee Phase gestartet wird
89 : * @var int
90 : * @access private
91 : */
92 : var $in_progress;
93 : /**
94 : * Gibt an, wann diese Phase abgeschlossen sein sollte
95 : * @var int
96 : * @access private
97 : */
98 : var $deadline;
99 : /**
100 : * ID des Kurses, der das Planspiel enthält, zu dem diese Phase gehört
101 : * @var int
102 : * @access private
103 : */
104 : var $courseID;
105 : /**
106 : * Array mit Team-IDs, die dieser Phase zugeordnet sind
107 : * @var array
108 : * @access private
109 : */
110 : var $teamIDs;
111 : /**
112 : * Array mit Document-Objekten, die zu dieser Phase gehören
113 : * @var array
114 : * @access private
115 : */
116 : var $documents;
117 : /**
118 : * Konstruktor
119 : * Liest die Daten der Phase aus, deren ID übergeben wurde
120 : * oder erzeugt ein neues Phasen-Objekt mit der ID 0.
121 : *
122 : * @access public
123 : * @param int $ID ID der Phase oder 0 für neue Phase
124 : * @param int $planspielID Bei neuen Phasen die ID des Planspiels, zu dem die Phase gehört
125 : */
126 : function Phase($ID, $planspielID = 0) {
127 0 : global $db, $settings;
128 0 : $dbp = $settings["dbPrefix"];
129 0 : if (strval(intval($ID)) == $ID && $ID > 0) {
130 0 : $this->ID = intval($ID);
131 0 : $result = $db->get_row("SELECT * FROM {$dbp}planspiel_phase WHERE id='$ID'");
132 0 : if ($db->num_rows) {
133 0 : $this->planspielID = intval($result->planspiel_id);
134 0 : $this->name = $result->name;
135 0 : $this->description = $result->description;
136 0 : $this->responsibleUserID = intval($result->responsible_user);
137 0 : $this->order = intval($result->phase_order);
138 0 : $this->isMilestone = (bool)$result->is_milestone;
139 0 : $this->isFinished = (bool)$result->finished;
140 0 : $this->deadline = $result->deadline;
141 0 : $this->in_progress = $result->in_progress;
142 0 : $this->courseID = intval($db->get_var("SELECT course_id FROM {$dbp}planspiel WHERE id='$this->planspielID'"));
143 0 : $teamIDs = $db->get_col("SELECT team_id FROM {$dbp}planspiel_phase_team WHERE phase_id='$this->ID' ORDER BY team_id");
144 0 : if ($db->num_rows) {
145 0 : $this->teamIDs = array_map("intval", $teamIDs);
146 0 : } else {
147 0 : $this->teamIDs = array();
148 : }
149 0 : } else {
150 0 : $this->setDefaultValues($planspielID);
151 : }
152 0 : } else {
153 0 : $this->setDefaultValues($planspielID);
154 : }
155 0 : }
156 : /**
157 : * Setzt die Standardwerte für ein neues Phasen-Objekt.
158 : *
159 : * @access private
160 : * @param int $planspielID ID des Planspiels bei neuer Phase
161 : * @return void
162 : */
163 : function setDefaultValues($planspielID) {
164 0 : global $db, $settings;
165 0 : $dbp = $settings["dbPrefix"];
166 0 : $this->ID = 0;
167 0 : $this->planspielID = intval($planspielID);
168 0 : $this->name = "";
169 0 : $this->description = "";
170 0 : $this->responsibleUserID = 0;
171 0 : $this->order = intval($db->get_var("SELECT MAX(phase_order) FROM {$dbp}planspiel_phase WHERE planspiel_id='$this->planspielID'")) +1;
172 0 : $this->isMilestone = false;
173 0 : $this->isFinished = false;
174 0 : $this->courseID = $_SESSION["course"];
175 0 : $this->teamIDs = array();
176 0 : $this->in_progress = 0;
177 0 : }
178 : /**
179 : * Gibt das Formular zur Auswahl der Teams aus, denen die Phase zugeordnet werden soll.
180 : * Sind keine Teams in diesem Kurs vorhanden, wird direkt showEditForm() aufgerufen.
181 : *
182 : * @access public
183 : * @return void
184 : */
185 : function showTeamForm() {
186 0 : $teams = TeamList::getTeams((int)$this->courseID);
187 0 : if (empty($teams)) {
188 0 : $this->showEditForm();
189 0 : return;
190 : }
191 0 : $form = new Formular();
192 0 : $form->setTemplate("<table class='tableBorder'>", "<tr valign='top'><td>", "<td>");
193 0 : $form->setButtons(1, "Weiter");
194 0 : $form->addRawCode("<tr><td colspan='2' class='tableHead'>".($this->ID > 0 ? "Phase bearbeiten" : "Neue Phase") ."</td></tr>");
195 0 : $form->addInput("hidden", "phaseID", "", 0, $this->ID);
196 0 : $form->addInput("hidden", "ID", "", 0, $this->planspielID);
197 0 : foreach($teams as $team) {
198 0 : $form->addToNextTag("id='team".$team->getID() ."'");
199 0 : $form->addInput("checkbox", "team[]", "<label for='team".$team->getID() ."'>".Data::toHTML($team->getName(), false) ."</label>", 0, $team->getID(), in_array($team->getID(), $this->teamIDs));
200 0 : }
201 0 : $form->addButtons();
202 0 : echo "<p>Bitte wählen Sie hier zunächst die Teams, denen die Phase zugeordnet werden soll.</p>";
203 0 : echo $form->getForm();
204 0 : }
205 : /**
206 : * Zeigt das Formular zum Bearbeiten der Phase an.
207 : *
208 : * @access public
209 : * @param array $teams Array mit Team-IDs, denen die Phase zugeordnet sein soll
210 : * @return void
211 : */
212 : function showEditForm($teams = 0) {
213 0 : global $db, $settings;
214 0 : $dbp = $settings["dbPrefix"];
215 0 : $planspielRoles = PlanspielList::getPlanspielRoleIDs($_SESSION["course"]);
216 0 : $ID = $this->ID;
217 0 : $form = new Formular();
218 0 : $form->setTemplate("<table class='contentTable'>", "<tr valign='top'><td>", "<td>");
219 0 : $form->setButtons(1, "Speichern");
220 0 : $form->addRawCode("<tr><td colspan='2' class='tableHead'>".($this->ID > 0 ? "Phase bearbeiten" : "Neue Phase") ."</td></tr>");
221 0 : $form->addInput("hidden", "phaseID", "", 0, $this->ID);
222 0 : $form->addInput("hidden", "ID", "", 0, $this->planspielID);
223 0 : $form->addInput("text", "name", "Name", 60, $this->name, 100);
224 0 : $form->addTextArea("description", "Beschreibung<br />(".BBCode::getTagOverviewLink() .")", 60, 10, $this->description);
225 0 : $user = array();
226 0 : if (is_array($teams) && !empty($teams) && $this->validateTeams($teams)) {
227 0 : $teams = array_map("intval", $teams);
228 0 : $utm = new UserTeamManagement((int)$this->courseID);
229 0 : foreach($teams as $teamID) {
230 0 : if ($teamID > 0) {
231 0 : $form->addInput("hidden", "team[]", "", 0, $teamID);
232 0 : $team = new Team($teamID);
233 0 : foreach($utm->getUsersOfTeam($teamID) as $userID) {
234 0 : $user[] = array(Data::toHTML($team->getName(), false) .": ".Data::toHTML($utm->users[$userID], false), $userID);
235 0 : }
236 0 : }
237 0 : }
238 0 : } else {
239 0 : $participants = Course::getParticipants($this->courseID, "all", "user.Nachname, user.Vorname");
240 0 : foreach($participants as $participant) {
241 0 : $user[] = array(Data::toHTML($participant->lastname.", ".$participant->firstname, false), $participant->userid);
242 0 : }
243 : }
244 0 : $form->addSelect("responsible", "Verantwortlicher", $user, 1, false, ($this->responsibleUserID > 0 ? $this->responsibleUserID : ""));
245 0 : $form->addMarker();
246 0 : echo $form->getForm(0);
247 :
248 0 : $form->addToNextTag("id='in_progress'");
249 0 : if($this->in_progress == '0'){
250 0 : echo "<tr valign='top'><td>Start der Phase</td><td>";
251 0 : $date = getdate(time()); //aktuelle Zeit
252 0 : $ds = new DateSelection($date["mday"], $date["mon"], $date["year"], $date["hours"], $date["minutes"]);
253 0 : $ds->clearStrings();
254 0 : $ds->printCalender("inProgress", "all");
255 0 : echo "</td></tr>";
256 0 : } else {
257 0 : $form->addRawCode("<tr><td>Bearbeitung</td><td>"."Diese Phase wurde am ".date("d.m.Y", $this->in_progress)." um ".date("H:i", $this->in_progress)." freigegeben."."</td></tr>");
258 : }
259 0 : echo "<tr valign='top'><td>Deadline</td><td>";
260 0 : if($this->deadline > 0){
261 0 : $date = getdate($this->deadline);
262 0 : $ds = new DateSelection($date["mday"], $date["mon"], $date["year"], $date["hours"], $date["minutes"]);
263 0 : }
264 : else{
265 0 : $date = getdate(time()+24*3600); //aktuelle Zeit + 24h
266 0 : $ds = new DateSelection($date["mday"], $date["mon"], $date["year"], $date["hours"], $date["minutes"]);
267 : }
268 0 : $ds->clearStrings();
269 0 : $ds->printCalender("deadline", "all");
270 0 : echo "</td></tr>";
271 0 : $form->addToNextTag("id='milestone'");
272 0 : $form->addInput("checkbox", "milestone", "<label for='milestone'>Meilenstein</label>", 60, ($this->isMilestone ? "1" : ""), $this->isMilestone);
273 0 : $form->addToNextTag("id='finished'");
274 0 : $form->addInput("checkbox", "finished", "<label for='finished'>Phase abgeschlossen</label>", 60, ($this->isFinished ? "1" : ""), $this->isFinished);
275 0 : $form->addButtons();
276 0 : echo $form->getForm(1);
277 0 : }
278 : /**
279 : * Listet die dieser Phase zugeordneten Dokumente auf.
280 : *
281 : * @access public
282 : * @return void
283 : */
284 : function listDocuments() {
285 0 : global $db, $settings;
286 0 : $dbp = $settings["dbPrefix"];
287 0 : $planspielRoles = PlanspielList::getPlanspielRoleIDs($this->courseID);
288 0 : $isLeader = $_SESSION["usergroup"] == ADMIN || ($_SESSION["usergroup"] == DOZENT && $this->courseID > 0) || (isset($_SESSION["roleID"]) && $_SESSION["roleID"] == $planspielRoles["phaseResponsible"] && $_SESSION["userid"] == $this->responsibleUserID) || isset($_SESSION["assistent"]);
289 0 : echo "<br /><a href='".PATH_TO_ROOT."planspiel/phasedetails.php?ID=".$this->ID."&tab=1' title='Phasendetails anzeigen'"."><img alt='Statistik anzeigen' src='".PATH_TO_ROOT."images/icon_planspiel_statistics.gif'/> Phasendetails anzeigen </a>";
290 0 : if (!$isLeader) {
291 0 : $planspiel = new Planspiel($this->planspielID);
292 0 : $isLeader = isset($_SESSION["roleID"]) && $_SESSION["roleID"] == $planspielRoles["leader"] && $_SESSION["userid"] == $planspiel->getLeaderID();
293 0 : }
294 0 : $docs = $this->getDocuments();
295 0 : if (!empty($docs)) {
296 0 : echo "<table class='contentTable'>\n";
297 0 : Output::echoTableHead("Dokumente der Phase »".Data::toHTML($this->name, false) ."«", 6);
298 0 : echo "<tr><th>Name</th><th>Bearbeiter/Reviewer</th><th>Status</th><th>Aufwand</th><th>Budget</th><th></th></tr>";
299 0 : foreach($docs as $doc) {
300 0 : $ID = $doc->getID();
301 0 : echo "<tr valign='top'>";
302 0 : echo "<td><b>".$doc->getLinkToFile() ."</b><br />";
303 0 : echo "<a href='".PATH_TO_ROOT.SCRIPT_NAME."?action=showDetails&ID=".$doc->getID() ."&phaseID=$this->ID&planspielID=$this->planspielID' title='Details anzeigen'"."><img alt='Statistik anzeigen' src='".PATH_TO_ROOT."images/icon_planspiel_statistics.gif'/> Details</a>";
304 0 : echo "</td><td>".$doc->getEditor() ."<br />";
305 0 : echo $doc->getReviewer() ."</td>";
306 0 : echo "<td>".Data::toHTML($doc->getStatusText(), false) ."<br />";
307 0 : $deadline = intval($db->get_var("SELECT deadline FROM {$dbp}planspiel_document WHERE ID='$ID'"));
308 0 : if($deadline == '0' || $deadline == NULL){
309 0 : echo "DL: n.d.";
310 0 : } else {
311 0 : echo "DL: ".date("d.m.Y H:i", $deadline);
312 : }
313 0 : echo "</td><td>";
314 0 : echo "A: ".$doc->getEstimatedEffort() ."<br />";
315 0 : echo "B: ".$doc->getDaysSpent() ."<br />";
316 0 : echo "C: ".$doc->getETC();
317 0 : echo "</td>";
318 0 : echo "<td>";
319 : //Budget Balken
320 0 : if($doc->getEstimatedEffort() == 0){
321 0 : $colors = new ColorIndicator("100", "0");
322 0 : } else {
323 0 : $colors = new ColorIndicator("100", (100*($doc->getDaysSpent())+($doc->getETC()))/$doc->getEstimatedEffort());
324 : }
325 0 : $colors->is_budget();
326 : ?> <table border="1" cellpadding="0" style= " height: 35px; border-collapse: collapse; border-color: #000000; width: 10px;" >
327 : <tr>
328 0 : <td title="<?php echo $colors->tooltip; ?>" style=" background-color:<?php echo $colors->budget_color; ?>;"> </td>
329 : </tr>
330 : </table>
331 0 : <?php
332 :
333 0 : echo "</td>";
334 0 : echo "<td>";
335 0 : $isEditor = isset($_SESSION["roleID"]) && $_SESSION["roleID"] == $planspielRoles["editor"] && $doc->getEditorUserID() == $_SESSION["userid"] ;
336 0 : $isReviewer = isset($_SESSION["roleID"]) && $_SESSION["roleID"] == $planspielRoles["reviewer"] && $doc->getReviewerUserID() == $_SESSION["userid"];
337 0 : if ($isLeader || $isEditor || $isReviewer ) {
338 0 : echo "<a href='".PATH_TO_ROOT.SCRIPT_NAME."?action=editDocument&ID=".$doc->getID() ."&phaseID=$this->ID&planspielID=$this->planspielID'>".Output::getIcon("icon_edit", "Bearbeiten") ."</a>";
339 0 : }
340 0 : if ($isLeader) {
341 0 : echo "<a href='".PATH_TO_ROOT.SCRIPT_NAME."?action=deleteDocument&ID=".$doc->getID() ."&phaseID=$this->ID&planspielID=$this->planspielID'>".Output::getIcon("icon_muell", "Löschen") ."</a>";
342 0 : }
343 0 : echo "</td></tr>";
344 0 : }
345 0 : echo "</table>";
346 0 : echo "<p>A: Geschätzter Aufwand<br/>B: Aufgewendete Zeit<br/>C: Geschätzte Zeit bis zum Abschluss<br/>(alle Angaben in Personentagen)<br/>DL: Deadline<br/>n.d.: nicht definiert</p>";
347 0 : } else {
348 0 : echo "<p>Es wurden noch keine Dokumente angelegt.</p>";
349 : }
350 0 : }
351 : /**
352 : * Versucht, die im übergebenen Array vorhandenen Daten anhand der
353 : * assoziativen Array-Indizes als neue Phasen-Daten abzuspeichern. Dabei
354 : * kann es sich zum Beispiel um das $_POST-Array handeln. Es werden dabei
355 : * entweder alle oder keine Daten gespeichert. Sind einige der Daten
356 : * fehlerhaft, wird ein String mit Fehlermeldungen zurückgeliefert, sonst
357 : * der boolsche Wert true.
358 : *
359 : * @access public
360 : * @param array $data Assoziatives Array mit den neuen Werten
361 : * @return mixed String mit Fehlermeldungen oder true bei Erfolg
362 : */
363 : function setData($data) {
364 0 : $errors = "";
365 0 : if (($result = $this->validateName($data["name"])) !== true) {
366 0 : $errors.= $result."\n";
367 0 : }
368 0 : if (($result = $this->validateResponsibleUserID($data["responsible"])) !== true) {
369 0 : $errors.= $result."\n";
370 0 : }
371 0 : if (isset($data["team"]) && ($result = $this->validateTeams($data["team"])) !== true) {
372 0 : $errors.= $result."\n";
373 0 : }
374 0 : if (($result = $this->validateDeadline(mktime($data["deadline_hour"], $data["deadline_minute"], 0, $data["deadline_month"], $data["deadline_day"], $data["deadline_year"]))) !== true) {
375 0 : $errors.= $result."\n";
376 0 : }
377 0 : if (empty($errors)) {
378 0 : if (!$this->setName($data["name"])) {
379 0 : return "Name konnte nicht gespeichert werden.";
380 : }
381 0 : if (!$this->setDescription($data["description"])) {
382 0 : return "Beschreibung konnte nicht gespeichert werden.";
383 : }
384 0 : if (!$this->setResponsibleUserID($data["responsible"])) {
385 0 : return "Verantwortlicher konnte nicht gespeichert werden.";
386 : }
387 0 : if (!$this->setMilestone(isset($data["milestone"]))) {
388 0 : return "Meilenstein konnte nicht gesetzt werden.";
389 : }
390 0 : if (!$this->setFinished(isset($data["finished"]))) {
391 0 : return "Phasenabschluss konnte nicht gesetzt werden.";
392 : }
393 0 : if (isset($data["team"]) && !$this->setTeams($data["team"])) {
394 0 : return "Teamauswahl konnte nicht gespeichert werden.";
395 : }
396 0 : if (!$this->setDeadline(mktime($data["deadline_hour"], $data["deadline_minute"], 0, $data["deadline_month"], $data["deadline_day"], $data["deadline_year"]))) {
397 0 : return "Deadline konnte nicht gespeichert werden.";
398 : }
399 0 : if (isset($data["inProgress_hour"]) && !$this->setInProgressSince(mktime($data["inProgress_hour"], $data["inProgress_minute"], 0, $data["inProgress_month"], $data["inProgress_day"], $data["inProgress_year"]))) {
400 0 : return "Startdatum konnte nicht gespeichert werden.";
401 : }
402 0 : return true;
403 : }
404 0 : return trim($errors);
405 : }
406 : /**
407 : * Erstellt den grundlegenden Datenbankeintrag für die Phase. Gesetzt werden
408 : * nur die Planspiel-ID und die Phasen-Position, die anderen Felder werden
409 : * mit ihren Standardwerten belegt.
410 : *
411 : * @access private
412 : * @return boolean Erfolgswert
413 : */
414 : function createPhase() {
415 0 : global $db, $settings;
416 0 : $dbp = $settings["dbPrefix"];
417 0 : $db->query("INSERT INTO {$dbp}planspiel_phase (planspiel_id, phase_order) VALUES ('$this->planspielID', '$this->order')");
418 0 : if ($db->rows_affected) {
419 0 : $this->ID = $db->insert_id;
420 0 : return true;
421 : }
422 0 : return false;
423 : }
424 : /**
425 : * Löscht diese Phase und die zugehörigen Dokumente.
426 : *
427 : * @access public
428 : * @return boolean Erfolgswert
429 : */
430 : function deletePhase() {
431 0 : global $db, $settings, $EZSQL_ERROR;
432 0 : $dbp = $settings["dbPrefix"];
433 0 : $errorCount = count($EZSQL_ERROR);
434 0 : $db->query("DELETE FROM {$dbp}planspiel_phase WHERE id='$this->ID'");
435 0 : $db->query("DELETE FROM {$dbp}planspiel_phase_team WHERE phase_id='$this->ID'");
436 0 : $db->query("UPDATE {$dbp}planspiel_phase SET phase_order=phase_order-1 WHERE phase_order>'$this->order' AND planspiel_id='$this->planspielID'");
437 0 : foreach($this->getDocuments() as $doc) {
438 0 : $doc->deleteDocument();
439 0 : }
440 0 : if (count($EZSQL_ERROR) > $errorCount) {
441 0 : return false;
442 : }
443 0 : $this->setDefaultValues($this->planspielID);
444 0 : return true;
445 : }
446 : /**
447 : * Gibt zurück, ob ein übergebenes Dokument ein Dokument dieser Phase ist.
448 : *
449 : * @access public
450 : * @param int $docID ID des Dokuments
451 : * @return boolean true, wenn das Dokument zu dieser Phase gehört, sonst false
452 : */
453 : function documentInPhase($docID) {
454 0 : if (strval(intval($docID)) != $docID || $docID < 0) {
455 0 : return false;
456 : }
457 0 : if ($docID == 0) {
458 0 : return true;
459 : }
460 0 : foreach($this->getDocuments() as $doc) {
461 0 : if ($doc->getID() == $docID) {
462 0 : return true;
463 : }
464 0 : }
465 0 : return false;
466 : }
467 : /**
468 : * Überprüft den übergebenen Namen auf Gültigkeit.
469 : *
470 : * @access public
471 : * @param string $name Der zu überprüfende String
472 : * @return mixed String mit Fehlerangabe oder true bei Erfolg
473 : */
474 : function validateName($name) {
475 0 : global $db, $settings;
476 0 : $dbp = $settings["dbPrefix"];
477 0 : $name = trim(Data::gpcUnescape($name));
478 0 : if (empty($name)) {
479 0 : return "Der Name wurde nicht angegeben.";
480 : }
481 0 : if (strlen($name) > 100) {
482 0 : return "Der Name ist zu lang.";
483 : }
484 0 : if ($this->ID == 0 && $db->get_var("SELECT COUNT(*) FROM {$dbp}planspiel_phase WHERE planspiel_id='$this->planspielID' AND name='".Data::toMysql($name, false) ."'")) {
485 0 : return "Der Name ist in diesem Planspiel bereits vergeben.";
486 : }
487 0 : return true;
488 : }
489 :
490 : function validateDeadline($deadline) {
491 :
492 0 : if ($this->deadline == $deadline) {
493 0 : return true;
494 : }
495 :
496 0 : $date = getdate(time());
497 0 : $tomorrow = mktime(23, 59, 59, $date["mon"], $date["mday"], $date["year"]);
498 0 : if ($deadline < $tomorrow) {
499 0 : return "Die Deadline muss mindestens einen Tag in der Zukunft liegen.";
500 : }
501 0 : return true;
502 : }
503 :
504 : /**
505 : * Überprüft die übergebene User-ID auf Gültigkeit.
506 : *
507 : * @access public
508 : * @param int $userID User-ID des Verantwortlichen
509 : * @return mixed String mit Fehlerangabe oder true bei Erfolg
510 : */
511 : function validateResponsibleUserID($userID) {
512 0 : global $db, $settings;
513 0 : $dbp = $settings["dbPrefix"];
514 0 : $users = $db->get_col("SELECT userID FROM {$dbp}user_course WHERE courseID='$this->courseID'");
515 0 : if (!in_array($userID, $users)) {
516 0 : return "Die Angabe des Verantwortlichen ist ungültig.";
517 : }
518 0 : return true;
519 : }
520 : /**
521 : * Überprüft die übergebenen Team-IDs auf Gültigkeit.
522 : *
523 : * @access public
524 : * @param array $teams Array mit Team-IDs
525 : * @return mixed String mit Fehlerangabe oder true bei Erfolg
526 : */
527 : function validateTeams($teams) {
528 0 : if (empty($teams)) {
529 0 : return true;
530 : }
531 0 : $availableTeams = TeamList::getTeams($this->courseID);
532 0 : $teamIDs = array();
533 0 : foreach($availableTeams as $team) {
534 0 : $teamIDs[] = $team->getID();
535 0 : }
536 0 : foreach($teams as $team) {
537 0 : if (!in_array($team, $teamIDs)) {
538 0 : return "Die Team-ID $team ist ungültig.";
539 : }
540 0 : }
541 0 : return true;
542 : }
543 : /**
544 : * Speichert den übergebenen String als neuen Namen dieser Phase.
545 : * Der String sollte vorher mit der Methode validateName() validiert worden
546 : * sein!
547 : *
548 : * @access public
549 : * @param string $name Zu speichernder Name
550 : * @return boolean Erfolgswert
551 : */
552 : function setName($name) {
553 0 : global $db, $settings;
554 0 : $dbp = $settings["dbPrefix"];
555 0 : $name = trim($name);
556 0 : if ($this->name == Data::gpcUnescape($name)) {
557 0 : return true;
558 : }
559 0 : if ($this->ID == 0) {
560 0 : if (!$this->createPhase()) {
561 0 : return false;
562 : }
563 0 : }
564 0 : $db->query("UPDATE {$dbp}planspiel_phase SET name='".Data::toMysql($name) ."' WHERE id='$this->ID'");
565 0 : if ($db->rows_affected) {
566 0 : $this->name = Data::gpcUnescape($name);
567 0 : return true;
568 : }
569 0 : return false;
570 : }
571 :
572 : function setDeadline($deadline) {
573 0 : global $db, $settings;
574 0 : $dbp = $settings["dbPrefix"];
575 :
576 0 : if ($this->deadline == $deadline) {
577 0 : return true;
578 : }
579 0 : $db->query("UPDATE {$dbp}planspiel_phase SET deadline='$deadline' WHERE id='$this->ID'");
580 0 : if ($db->rows_affected) {
581 0 : $this->deadline = $deadline;
582 0 : return true;
583 : }
584 0 : return false;
585 : }
586 :
587 : /**
588 : * Speichert den übergebenen String als neue Beschreibung dieser Phase.
589 : *
590 : * @access public
591 : * @param string $desc Zu speichernde Beschreibung
592 : * @return boolean Erfolgswert
593 : */
594 : function setDescription($desc) {
595 0 : global $db, $settings;
596 0 : $dbp = $settings["dbPrefix"];
597 0 : $desc = trim($desc);
598 0 : if ($this->description == Data::gpcUnescape($desc)) {
599 0 : return true;
600 : }
601 0 : if ($this->ID == 0) {
602 0 : if (!$this->createPhase()) {
603 0 : return false;
604 : }
605 0 : }
606 0 : if (empty($desc)) {
607 0 : $db->query("UPDATE {$dbp}planspiel_phase SET description=NULL WHERE id='$this->ID'");
608 0 : } else {
609 0 : $db->query("UPDATE {$dbp}planspiel_phase SET description='".Data::toMysql($desc) ."' WHERE id='$this->ID'");
610 : }
611 0 : if ($db->rows_affected) {
612 0 : $this->description = Data::gpcUnescape($desc);
613 0 : return true;
614 : }
615 0 : return false;
616 : }
617 : /**
618 : * Speichert die übergeben ID as neue User-ID des Verantwortlichen dieser Phase.
619 : * Die ID sollte vorher mit der Methode validateResponsibleUserID() validiert worden sein!
620 : *
621 : * @access public
622 : * @param int $userID User-ID
623 : * @return boolean Erfolgswert
624 : */
625 : function setResponsibleUserID($userID) {
626 0 : global $db, $settings;
627 0 : $dbp = $settings["dbPrefix"];
628 0 : $userID = trim($userID);
629 0 : if ($this->responsibleUserID == Data::gpcUnescape($userID)) {
630 0 : return true;
631 : }
632 0 : if ($this->ID == 0) {
633 0 : if (!$this->createPhase()) {
634 0 : return false;
635 : }
636 0 : }
637 0 : $db->query("UPDATE {$dbp}planspiel_phase SET responsible_user='".Data::toMysql($userID) ."' WHERE id='$this->ID'");
638 0 : if ($db->rows_affected) {
639 0 : $newUserID = intval(Data::gpcUnescape($userID));
640 0 : $roles = PlanspielList::getPlanspielRoleIDs($this->courseID);
641 0 : $urm = new UserRoleManagement($this->courseID);
642 0 : if (count(PlanspielList::getPlanspielWhereResponsible($this->courseID, $this->responsibleUserID)) == 0) {
643 0 : $urm->unsetRoleForUser($this->responsibleUserID, $roles["phaseResponsible"]);
644 0 : }
645 0 : $urm->setRoleForUser($newUserID, $roles["phaseResponsible"]);
646 0 : $this->responsibleUserID = $newUserID;
647 0 : return true;
648 : }
649 0 : return false;
650 : }
651 : /**
652 : * Legt fest, ob diese Phase ein Meilenstein ist.
653 : *
654 : * @access public
655 : * @param boolean $milestone true oder false
656 : * @return boolean Erfolgswert
657 : */
658 : function setMilestone($milestone) {
659 0 : global $db, $settings;
660 0 : $dbp = $settings["dbPrefix"];
661 0 : if (!is_bool($milestone)) {
662 0 : return false;
663 : }
664 0 : if ($this->isMilestone == $milestone) {
665 0 : return true;
666 : }
667 0 : if ($this->ID == 0) {
668 0 : if (!$this->createPhase()) {
669 0 : return false;
670 : }
671 0 : }
672 0 : $db->query("UPDATE {$dbp}planspiel_phase SET is_milestone='".intval($milestone) ."' WHERE id='$this->ID'");
673 0 : if ($db->rows_affected) {
674 0 : $this->isMilestone = $milestone;
675 0 : return true;
676 : }
677 0 : return false;
678 : }
679 : /**
680 : * Legt fest, ob diese Phase abgeschlossen ist.
681 : *
682 : * @access public
683 : * @param boolean $finished true oder false
684 : * @return boolean Erfolgswert
685 : */
686 : function setFinished($finished) {
687 0 : global $db, $settings;
688 0 : $dbp = $settings["dbPrefix"];
689 0 : if (!is_bool($finished)) {
690 0 : return false;
691 : }
692 0 : if ($this->isFinished == $finished) {
693 0 : return true;
694 : }
695 0 : if ($this->ID == 0) {
696 0 : if (!$this->createPhase()) {
697 0 : return false;
698 : }
699 0 : }
700 0 : $db->query("UPDATE {$dbp}planspiel_phase SET finished='".intval($finished) ."' WHERE id='$this->ID'");
701 0 : if ($db->rows_affected) {
702 0 : $this->isFinished = $finished;
703 0 : if ($finished) {
704 0 : $planspiel = new Planspiel($this->planspielID);
705 0 : $planspiel->setFinished($planspiel->getFinishedPhasesCount() == $planspiel->getPhasesCount());
706 0 : }
707 0 : return true;
708 : }
709 0 : return false;
710 : }
711 : function setInProgressSince($in_progressSince) {
712 0 : global $db, $settings;
713 0 : $dbp = $settings["dbPrefix"];
714 :
715 0 : if($this->in_progress == $in_progressSince){
716 0 : return true;
717 : }
718 0 : $db->query("UPDATE {$dbp}planspiel_phase SET in_progress='$in_progressSince' WHERE id='$this->ID'");
719 0 : if ($db->rows_affected) {
720 0 : $this->in_progress = $in_progressSince;
721 0 : return true;
722 : }
723 0 : return false;
724 : }
725 : /**
726 : * Speichert, welchen Teams diese Phase zugeordnet ist.
727 : * Die Daten sollten vorher mit der Methode validateTeams() validiert worden sein!
728 : *
729 : * @access public
730 : * @param array $teams Array mit Team-IDs
731 : * @return boolean Erfolgswert
732 : */
733 : function setTeams($teams) {
734 0 : global $db, $settings, $EZSQL_ERROR;
735 0 : $dbp = $settings["dbPrefix"];
736 0 : if (is_array($teams)) {
737 0 : $teams = array_map("intval", $teams);
738 0 : sort($teams);
739 0 : }
740 0 : if ($this->teamIDs == $teams) {
741 0 : return true;
742 : }
743 0 : if ($this->ID == 0) {
744 0 : if (!$this->createPhase()) {
745 0 : return false;
746 : }
747 0 : }
748 0 : $errorCount = count($EZSQL_ERROR);
749 0 : $db->query("DELETE FROM {$dbp}planspiel_phase_team WHERE phase_id='$this->ID'");
750 0 : if (!empty($teams)) {
751 0 : $db->query("INSERT INTO {$dbp}planspiel_phase_team (phase_id, team_id) VALUES ('$this->ID', '".implode("'), ('$this->ID', '", $teams) ."')");
752 0 : }
753 0 : return $errorCount == count($EZSQL_ERROR);
754 : }
755 : /**
756 : * Legt die Position der Phase zwischen den anderen des Planspiels fest.
757 : *
758 : * @access public
759 : * @param int $order Position der Phase
760 : * @return boolean Erfolgswert
761 : */
762 : function setOrder($order) {
763 0 : global $db, $settings;
764 0 : $dbp = $settings["dbPrefix"];
765 0 : if ($this->order == $order) {
766 0 : return true;
767 : }
768 0 : if ($this->ID == 0) {
769 0 : if (!$this->createPhase()) {
770 0 : return false;
771 : }
772 0 : }
773 0 : $db->query("UPDATE {$dbp}planspiel_phase SET phase_order='".intval($order) ."' WHERE id='$this->ID'");
774 0 : if ($db->rows_affected) {
775 0 : $this->order = intval($order);
776 0 : return true;
777 : }
778 0 : return false;
779 : }
780 : /**
781 : * Gibt die ID der Phase zurück.
782 : *
783 : * @access public
784 : * @return int ID der Phase
785 : */
786 : function getID() {
787 0 : return $this->ID;
788 : }
789 : /**
790 : * Gibt den Namen dieser Phase zurück.
791 : *
792 : * @access public
793 : * @return string Name der Phase
794 : */
795 : function getName() {
796 0 : return $this->name;
797 : }
798 : /**
799 : * Gibt die Beschreibung dieser Phase zurück.
800 : *
801 : * @access public
802 : * @param boolean $bbcode Gibt an, ob BBCode in der Beschreibung bereits umgewandelt werden soll.
803 : * @return string Beschreibung der Phase
804 : */
805 : function getDescription($bbcode = true) {
806 0 : if ($bbcode) {
807 0 : $bb = new BBCode();
808 0 : return $bb->parse($this->description);
809 : }
810 0 : return $this->description;
811 : }
812 : /**
813 : * Gibt den Namen, Rolle und Teamzugehörigkeit des Verantwortlichen dieser Phase zurück.
814 : * Der Name ist verlinkt auf das Profil des Benutzers, die Rolle auf deren Eigenschaftenseite.
815 : *
816 : * @access public
817 : * @return string HTML-String mit Angaben zum Verantwortlichen
818 : */
819 : function getResponsibleUser() {
820 0 : global $db, $settings;
821 0 : $dbp = $settings["dbPrefix"];
822 0 : $urm = new UserRoleManagement($this->courseID);
823 0 : $utm = new UserTeamManagement($this->courseID);
824 0 : $responsible = "<a href='".PATH_TO_ROOT."user/homepage.php?user=$this->responsibleUserID'>".Data::toHTML($db->get_var("SELECT CONCAT(Nachname, ', ', Vorname) FROM {$dbp}user WHERE ID='$this->responsibleUserID'"), false) ."</a>";
825 0 : $team = $utm->getTeamOfUser($this->responsibleUserID);
826 0 : return $responsible;
827 : }
828 : /**
829 : * Gibt die User-ID des Verantwortlichen der Phase zurück.
830 : *
831 : * @access public
832 : * @return int User-ID des Verantwortlichen
833 : */
834 : function getResponsibleUserID() {
835 0 : return $this->responsibleUserID;
836 : }
837 : /**
838 : * Gibt die Position der Phase zwischen den anderen Phasen des Planspiels zurück.
839 : *
840 : * @access public
841 : * @return int Position der Phase
842 : */
843 : function getOrder() {
844 0 : return $this->order;
845 : }
846 : /**
847 : * Gibt zurück, ob die Phase ein Meilenstein ist.
848 : *
849 : * @access public
850 : * @return boolean true, wenn die Phase ein Meilenstein ist, sonst false
851 : */
852 : function isMilestone() {
853 0 : return $this->isMilestone;
854 : }
855 : /**
856 : * Gibt zurück, ob die Phase abgeschlossen ist.
857 : *
858 : * @access public
859 : * @return boolean true, wenn die Phase abgeschlossen ist, sonst false
860 : */
861 : function isFinished() {
862 0 : return $this->isFinished;
863 : }
864 : /**
865 : * Gibt zurück, ob diese Phase gerade die aktuell in Bearbeitung befindliche ist.
866 : *
867 : * @access public
868 : * @return boolean true, wenn diese Phase die aktuelle ist, sonst false
869 : */
870 : function isCurrent() {
871 0 : global $db, $settings;
872 0 : $dbp = $settings["dbPrefix"];
873 0 : if ($this->isFinished) {
874 0 : return false;
875 : }
876 0 : return $db->get_var("SELECT COUNT(*) FROM {$dbp}planspiel_phase WHERE planspiel_id='$this->planspielID' AND phase_order<'$this->order' AND finished=1") == $this->order-1;
877 : }
878 : /**
879 : * Gibt die Anzahl der bereits fertiggestellten Dokumente dieser Phase zurück.
880 : *
881 : * @access public
882 : * @return int Anzahl der fertigen Dokumente
883 : */
884 : function getFinishedDocumentsCount() {
885 0 : $finished = 0;
886 0 : foreach($this->getDocuments() as $doc) {
887 0 : if ($doc->isFinished()) {
888 0 : $finished++;
889 0 : }
890 0 : }
891 0 : return $finished;
892 : }
893 : /**
894 : * Gibt die Anzahl der Dokumente dieser Phase zurück.
895 : *
896 : * @access public
897 : * @return int Anzahl der Dokumente
898 : */
899 : function getDocumentsCount() {
900 0 : return count($this->getDocuments());
901 : }
902 : /**
903 : * Gibt einen Link zum Neuerstellen eines Dokumentes für diese Phase zurück.
904 : *
905 : * @access public
906 : * @return string HTML-Link
907 : */
908 : function getNewDocumentLink() {
909 0 : return "<p><a href='document.php?action=editDocument&ID=0&phaseID=$this->ID&planspielID=$this->planspielID'>Neues Dokument anlegen</a></p>";
910 : }
911 : /**
912 : * Gibt die Document-Objekte dieser Phase zurück.
913 : *
914 : * @access public
915 : * @return array Document-Objekte
916 : */
917 : function getDocuments() {
918 0 : global $db, $settings;
919 0 : $dbp = $settings["dbPrefix"];
920 0 : if (!isset($this->documents)) {
921 0 : $this->documents = array();
922 0 : $docIDs = $db->get_col("SELECT id FROM {$dbp}planspiel_document WHERE phase_id='$this->ID' ORDER BY name");
923 0 : if (!empty($docIDs)) {
924 0 : foreach($docIDs as $docID) {
925 0 : $this->documents[] = new Document($docID);
926 0 : }
927 0 : }
928 0 : }
929 0 : return $this->documents;
930 : }
931 : /**
932 : * Gibt den auf die Dokumentenübersicht verlinkten Phasennamen zurück.
933 : *
934 : * @access public
935 : * return string Verlinkter Phasenname
936 : */
937 : function getLink() {
938 0 : return "<a href='".PATH_TO_ROOT."planspiel/document.php?phaseID=".$this->ID."&planspielID=".$this->planspielID."' title='Zur Dokumentenübersicht'>".Data::toHTML($this->name, false) ."</a>";
939 : }
940 : /**
941 : * Gibt den geschätzten Aufwand in PT zurück.
942 : *
943 : * @access public
944 : * @return float Personentage
945 : */
946 : function getEstimatedEffort() {
947 0 : $sum = 0;
948 0 : foreach($this->getDocuments() as $doc) {
949 0 : $sum+= $doc->getEstimatedEffort();
950 0 : }
951 :
952 0 : return number_format($sum, 2);
953 : }
954 : /**
955 : * Gibt die bisher aufgewendeten PT zurück.
956 : *
957 : * @access public
958 : * @return float Personentage
959 : */
960 : function getDaysSpent() {
961 0 : $sum = 0;
962 0 : foreach($this->getDocuments() as $doc) {
963 0 : $sum+= $doc->getDaysSpent();
964 0 : }
965 :
966 : // Ermittle und addiere die Aufwände des Spielleiters
967 0 : $this->planspielBudget = new PlanspielBudget($this->planspielID);
968 : // Auf 2 Nachkommastellen kürzen
969 0 : $sum += number_format($this->planspielBudget->GetPhasenVerantwortlicherBudget($this->ID), 2, '.', '');
970 :
971 0 : return number_format($sum, 2);
972 : }
973 : /**
974 : * Gibt die ETC in PT zurück.
975 : *
976 : * @access public
977 : * @return float Personentage
978 : */
979 : function getETC() {
980 0 : $sum = 0;
981 0 : foreach($this->getDocuments() as $doc) {
982 0 : $sum+= $doc->getETC();
983 0 : }
984 0 : return number_format($sum, 2);
985 : }
986 : }
|